package com.example.lck;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class WareHouse {
    private int capacity;
    private Queue<Goods> goodsQueue;
    private Lock lock = new ReentrantLock();
    // 等待不同条件的线程放到不同的等待队列中，而synchronized的唤醒是随机的
    private Condition addCondition = lock.newCondition();
    private Condition getCondition = lock.newCondition();

    public WareHouse(int capacity) {
        this.capacity = capacity;
        goodsQueue = new LinkedList<>();
    }

    public void add(Goods goods) {
        lock.lock();
        while (goodsQueue.size() == capacity) {
            System.out.println("warehouse is full, waiting ...");
            try {
                // 等待已消费信号
                getCondition.await();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        goodsQueue.offer(goods);
        // 已生产的信号，通知消费
        addCondition.signal();
        lock.unlock();
    }

    public Goods get() {
        lock.lock();
        while (goodsQueue.isEmpty()) {
            System.out.println("warehouse is empty, waiting ...");
            try {
                // 等待已生产的信号
                addCondition.await();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        Goods g = goodsQueue.poll();
        // 已消费的信号，通知生产
        getCondition.signal();
        lock.unlock();

        return g;
    }

}
